#pragma once

namespace cr
{
	template<typename T>
	struct Handle
	{
	public:

		Handle()
			: m_pObj( 0 )
		{
		}

		template<typename U>
		Handle(const Handle<U>& rOther)
			: m_pObj( static_cast<T*>(rOther.GetPtr()) )
		{
		}

		template<typename U>
		Handle(U* pObj)
		{
			m_pObj = pObj;
		}

		Handle(T* pObj)
		{
			m_pObj = pObj;
		}

		Handle(T& rObj)
		{
			m_pObj = &rObj;
		}

		Handle<T> operator = (T* pObj)
		{
			m_pObj = pObj;
			return *this;
		}

		template<typename U>
		Handle<T> operator = (U* pObj)
		{
			m_pObj = static_cast<T*>( pObj );
			return *this;
		}

		T* operator -> () const
		{
			return m_pObj;
		}

		T& operator * () 
		{
			return *m_pObj;
		}

		T* GetPtr() const
		{
			return m_pObj;
		}

		bool IsValid() const
		{
			return ( m_pObj != 0 );
		}

		void Destroy()
		{
			delete m_pObj;
			m_pObj = 0;
		}

		bool operator == (const Handle<T>& rOther )
		{
			return m_pObj == rOther.m_pObj;
		}

		bool operator != (const Handle<T>& rOther )
		{
			return m_pObj != rOther.m_pObj;
		}

	private:

		T*	m_pObj;
	};
}